Add CommandService/RequestFastUpdates and system diagnostics view - #23
Conversation
Two additions surfaced from reverse-engineering com.quilt.android 255. CommandService / RequestFastUpdates - New core.protos.home_datastore.CommandService with RequestFastUpdates, wrapped by QuiltClient.request_fast_updates(reason=..., system_id=...). Asks the cloud to raise a system's telemetry cadence — the lever the mobile app pulls on user activity or a degraded local mesh. New FastUpdateReason enum (UNSPECIFIED / LOCAL_COMMS_UNHEALTHY / USER_ACTIVITY). Verified reachable against production. Diagnostics view - QuiltClient.get_diagnostics() and SystemSnapshot.diagnostics() return a new SystemDiagnostics: the per-indoor-unit fault/condition matrix (including the outdoor-unit / refrigerant conditions surfaced through each IDU), refrigerant-circuit temperatures, and per-unit power. New IndoorUnitDiagnostics / OutdoorUnitDiagnostics models and IndoorUnitConditions.active / .states() helpers. New `quilt diagnostics` CLI command (--faults-only, --output json). The outdoor unit's own raw board sensors are withheld from the cloud plane and are flagged as such rather than reported. Tests, reference docs, and CHANGELOG updated. ruff / mypy / pytest (89% cov) / mkdocs --strict all green.
Not consumed by CI (which resolves from pyproject.toml) and this is a published library, so consumers never use the lockfile. Keeps a dev-only, already-drifting lock out of version control.
There was a problem hiding this comment.
🟡 Not ready to approve
IndoorUnitConditions.states() can raise ValueError on unknown proto enum integers, which would break diagnostics assembly and the CLI at runtime.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR extends the async Quilt client library with (1) a new cloud-only CommandService/RequestFastUpdates RPC wrapper to request higher telemetry cadence, and (2) an “installer-style” diagnostics view derived from snapshot data (plus a new quilt diagnostics CLI command), with accompanying proto/stub regeneration, tests, and documentation updates.
Changes:
- Add
CommandService.request_fast_updates()andQuiltClient.request_fast_updates()backed by new proto types (RequestFastUpdatesRequest,FastUpdateReason). - Add snapshot-derived diagnostics models (
SystemDiagnostics,IndoorUnitDiagnostics,OutdoorUnitDiagnostics),SystemSnapshot.diagnostics(), andQuiltClient.get_diagnostics(). - Add a
quilt diagnosticsCLI command, tests for both features, and update reference/docs/changelog.
File summaries
| File | Description |
|---|---|
| tests/test_diagnostics.py | Adds coverage for condition helpers, diagnostics aggregation, client wrapper, and CLI output modes. |
| tests/test_command.py | Adds coverage for RequestFastUpdates request construction, error translation, and client wrapper behavior. |
| src/quilt_hp/services/command.py | Introduces a service wrapper around the generated CommandServiceStub for RequestFastUpdates. |
| src/quilt_hp/models/system.py | Adds SystemSnapshot.diagnostics() to assemble a SystemDiagnostics view from a snapshot. |
| src/quilt_hp/models/indoor_unit.py | Adds IndoorUnitConditions.FIELD_NAMES plus active/states() helpers and refactors any_active. |
| src/quilt_hp/models/enums.py | Adds the public FastUpdateReason IntEnum. |
| src/quilt_hp/models/diagnostics.py | Adds new diagnostics dataclasses and constructors (from_indoor_unit, from_outdoor_unit). |
| src/quilt_hp/models/init.py | Re-exports new diagnostics models, FastUpdateReason, and IndoorUnitConditions. |
| src/quilt_hp/client.py | Wires in CommandService, adds get_diagnostics(), and adds request_fast_updates(). |
| src/quilt_hp/cli/main.py | Adds quilt diagnostics command and formatting helpers; supports summary and JSON output. |
| src/quilt_hp/_proto/quilt_hds_pb2.pyi | Regenerated type stubs to include FastUpdateReason and RequestFastUpdatesRequest. |
| src/quilt_hp/_proto/quilt_hds_pb2.py | Regenerated protobuf module to include new enum/message/service descriptors. |
| src/quilt_hp/_proto/quilt_hds_pb2_grpc.py | Regenerated gRPC stubs to include CommandServiceStub and server helpers. |
| proto/cleaned/quilt_hds.proto | Adds FastUpdateReason, RequestFastUpdatesRequest, and CommandService to the cleaned proto source. |
| docs/reference/models.md | Documents CommandService and the new diagnostics models/enums. |
| docs/reference/grpc-services-matrix.md | Documents the new CommandService/RequestFastUpdates RPC mapping. |
| docs/reference/client.md | Documents get_diagnostics() and request_fast_updates() public client APIs. |
| docs/how-to/cli-scripting.md | Adds CLI scripting examples for the new diagnostics command. |
| CHANGELOG.md | Adds unreleased entries describing both new features and their scope/limitations. |
| .gitignore | Ignores uv.lock with rationale comment. |
Review details
Files not reviewed (1)
- src/quilt_hp/_proto/quilt_hds_pb2.py: Generated file
- Files reviewed: 18/20 changed files
- Comments generated: 1
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| def states(self) -> dict[str, ConditionState]: | ||
| """Every condition mapped to its :class:`ConditionState`.""" | ||
| return {name: ConditionState(getattr(self, name)) for name in self.FIELD_NAMES} |
There was a problem hiding this comment.
Good catch — fixed in 42a19ec. IndoorUnitConditions.states() now routes each value through a _safe_condition_state() helper that falls back to UNSPECIFIED on unknown wire integers, matching the defensive pattern used for OutdoorUnit.hvac_state. (.active/.any_active were already safe — they compare raw ints and never construct the enum.) Added a regression test (test_conditions_tolerates_unknown_wire_value).
proto3 preserves unknown enum integers, so ConditionState(value) could raise ValueError and break diagnostics()/the CLI if the backend adds a new condition state. states() now falls back to UNSPECIFIED for unknown values, matching the defensive pattern used for OutdoorUnit.hvac_state. (.active was already safe — it compares raw ints.) Addresses Copilot review feedback.
There was a problem hiding this comment.
🟢 Ready to approve
The changes are cohesive, well-tested, and align with existing service/model/client layering without introducing verified defects in the modified regions.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Files not reviewed (1)
- src/quilt_hp/_proto/quilt_hds_pb2.py: Generated file
- Files reviewed: 18/20 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Two additions surfaced from reverse-engineering
com.quilt.androidversionCode 255. Reviewable commit-by-commit.1.
CommandService/RequestFastUpdatesA new service in the
home_datastorepackage (cloud stub only — no local endpoint).CommandService+RequestFastUpdatesRequest+FastUpdateReasonto the proto and regenerates stubs.QuiltClient.request_fast_updates(reason=..., system_id=...)— asks the cloud to raise a system's telemetry cadence, the same lever the mobile app pulls on user activity or a degraded local mesh.FastUpdateReasonenum:UNSPECIFIED/LOCAL_COMMS_UNHEALTHY/USER_ACTIVITY.Empty, request accepted).2. Diagnostics view
Surfaces the installer-style diagnostic picture from data the cloud API already returns — on the indoor units.
QuiltClient.get_diagnostics()/SystemSnapshot.diagnostics()→ newSystemDiagnostics.outdoor_unit_communication_error,defrost_cycle,oil_return, …), refrigerant-circuit temps (coil / gas-pipe / liquid-pipe / inlet / outlet), humidity, and power.IndoorUnitDiagnostics,OutdoorUnitDiagnostics,SystemDiagnostics;IndoorUnitConditions.active/.states()helpers.quilt diagnostics(--faults-only,--output json).OutdoorUnitDiagnostics.raw_sensors_availableisFalseand this is flagged rather than faked.Testing
ruff check·ruff format·mypy(46 files) ·pytest(293 passed, 89% coverage; newdiagnostics.pyandcommand.pyat 100%) ·check_docs_nav·mkdocs build --strict— all green. Docs updated:client.md,models.md,grpc-services-matrix.md,cli-scripting.md, CHANGELOG.Note:
uv.lockSecond commit gitignores
uv.lock. It isn't consumed by CI (which resolves frompyproject.toml), this is a published library (consumers never use the lock), and the tracked-but-untracked copy had already drifted out of sync. If dev/CI later standardize onuv sync --locked, commit it then and wire CI to it.